using System;
using RapidHDL;

namespace NegBinary
{
    /// <summary>
    /// Summary description for AndGate.
    /// </summary>
    public class NegBinaryAdd : TruthTableComponent
    {
        public NodeVector InputANodes;
        public NodeVector InputBNodes;
        public NodeVector OutputNodes;

        int iInputWidth;
        long lLowRange = 0;
        long lHighRange = 0;


        public NegBinaryAdd(Component poParentComponent, string psName, int piInputWidth)
            : base(poParentComponent, psName)
        {
            iInputWidth = piInputWidth;
            this.GetTruthTable("NegabinaryAdd", iInputWidth * 2, iInputWidth * 2 + 1);
            InputANodes = this.CreateNodeVector("InA", iInputWidth, NodeFlowType.Sink);
            InputBNodes = this.CreateNodeVector("InB", iInputWidth, NodeFlowType.Sink);
            OutputNodes = this.CreateNodeVector("Out", iInputWidth + 4 + 1, NodeFlowType.Source);
        }

        public long LowRange
        {
            get { return lLowRange; }
        }

        public long HighRange
        {
            get { return lHighRange; }
        }

        protected override void GenerateTruthTable()
        {
            long lTest = 0;
            bool bOverflow = false;
            
            while (!bOverflow)
            {
                try
                {
                    string sTest = Convert.LongToNegBinary(lTest + 1, iInputWidth);
                    lTest = lTest + 1;
                }
                catch
                {
                    bOverflow = true;
                }                
            }
            lHighRange = lTest;

            bOverflow = false;
            while (!bOverflow)
            {
                try
                {
                    string sTest = Convert.LongToNegBinary(lTest - 1, iInputWidth);
                    lTest = lTest  - 1;
                }
                catch
                {
                    bOverflow = true;
                }
            }
            lLowRange = lTest;

            this.TruthTable.AddTableEntry("default", new string('X',iInputWidth * 2 + 1));

            for (long lA = lLowRange; lA <= lHighRange; lA++)
            {
                for (long lB = lLowRange; lB <= lHighRange; lB++)
                {
                    long lAnswer = lA * lB;
                    string sInput = Convert.LongToNegBinary(lA, iInputWidth) + Convert.LongToNegBinary(lB, iInputWidth);
                    string sResult = Convert.LongToNegBinary(lAnswer, iInputWidth * 2 + 1);
                    this.TruthTable.AddTableEntry(sInput, sResult);
                }
            }
        }

        public override bool TransformStructureToVerilog()
        {
            WriteVerilogLookupTable();
            return true;
        }
    }
}
